package com.leyou.user.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.auth.pojo.UserInfo;
import com.leyou.cart.pojo.Cart;
import com.leyou.common.pojo.PageResult;
import com.leyou.common.utils.JsonUtils;
import com.leyou.common.utils.NumberUtils;
import com.leyou.item.pojo.Sku;
import com.leyou.user.client.GoodsClient;
import com.leyou.user.filter.LoginInterceptor;
import com.leyou.user.mapper.AddressMapper;
import com.leyou.user.mapper.CollectMapper;
import com.leyou.user.mapper.UserMapper;
import com.leyou.user.pojo.Address;
import com.leyou.user.pojo.Collect;
import com.leyou.user.pojo.User;
import com.leyou.user.utils.CodecUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private CollectMapper collectMapper;


    @Autowired
    private GoodsClient goodsClient;


    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    static final String KEY_PREFIX = "user:code:phone:";

    static final String KEY_PREFIX2 = "ly:cart:uid:";

    static final Logger logger = LoggerFactory.getLogger(UserService.class);

    //生成验证码并发送
    public Boolean sendVerifyCode(String phone) {
        // 生成验证码
        String code = NumberUtils.generateCode(6);

        try{
            //发送短信
            Map<String, String> msg = new HashMap<>();
            msg.put("phone", phone);
            msg.put("code", code);

            this.amqpTemplate.convertAndSend("leyou.sms.exchange","sms.verify.code",msg);

            // 将code存入redis
            this.redisTemplate.opsForValue().set(KEY_PREFIX+phone,code,5, TimeUnit.MINUTES);
            return true;
        }catch (Exception e){
            logger.error("发送短信失败。phone：{}， code：{}", phone, code);
            return false;
        }
    }

    //注册的方法
    public Boolean register(User user, String code) {
        // 从redis取出验证码
        String key=KEY_PREFIX+user.getPhone();
        String codeCache = redisTemplate.opsForValue().get(key);
        if(StringUtils.isBlank(code) || !code.equals(codeCache)){
            //为空,验证码过期 || 验证不正确
           return false;
        }

        //补全数据
        user.setId(null);
        user.setCreated(new Date());
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);
        // 对密码进行加密
        user.setPassword(CodecUtils.md5Hex(user.getPassword(), salt));

        // 将数据写入数据库
        boolean boo = this.userMapper.insertSelective(user) == 1;

        // 如果注册成功，删除redis中的code
        if (boo) {
            try {
                this.redisTemplate.delete(key);
            } catch (Exception e) {
                logger.error("删除缓存验证码失败，code：{}", code, e);
            }
        }

        return boo;
    }

    //校验数据是否可用
    public Boolean checkDate(String data, Integer type) {
        User user = new User();

        switch (type){
            case 1:
                user.setUsername(data);
                break;
            case 2:
                user.setPhone(data);
                break;
            default:
                return null;
        }
        //返回true,表示数据无该数据,即数据可用
        return userMapper.selectCount(user) == 0;
    }

    //校验用户名和密码是否正确的方法
    public User queryUserByUserName(String username, String password) {
        // 查询
        User u = new User();
        u.setUsername(username);
        User user = userMapper.selectOne(u);

        // 校验用户名
        if(user==null){
            return null;
        }
        System.out.println(user);

        //校验密码
        if(!user.getPassword().equals(CodecUtils.md5Hex(password,user.getSalt()))){
            return null;
        }

        // 用户名密码都正确
        return user;
    }

    // 根据用户名查询地址
    public List<Address> queryAddressByUserId(Long userId) {
        Address record = new Address();
        return this.addressMapper.select(record);
    }

    /**
     * 新增用户地址
     * @param address
     */
    public void addAddress(Address address) {
        address.setIsDefault(0);
        this.addressMapper.insertSelective(address);
    }

    /**
     * 根据id删除用户地址
     * @param id
     */
    public void deleteAdd(Long id) {
        this.addressMapper.deleteByPrimaryKey(id);
    }

    @Transactional
    public void setDefaultAddressbyUserId(Long id, Long userId) {

        // 查询该用户的所有地址,的默认地址值为0
        Address address = new Address();
        address.setUserId(userId);
        address.setIsDefault(0);
        this.addressMapper.updatesetDefaultAddressbyUserId(userId);

        Address address1 = new Address();
        address1.setId(id);
        address1.setIsDefault(1);
        this.addressMapper.updateByPrimaryKeySelective(address1);


    }

    /**
     * 根据地址id查询地址
     * @param id
     * @return
     */
    public Address queryAddersById(Long id) {
        return this.addressMapper.selectByPrimaryKey(id);
    }

    /**
     * 修改地址
     * @param address
     */
    public void upadtaAddress(Address address) {
        address.setIsDefault(0);
        this.addressMapper.updateByPrimaryKeySelective(address);
    }

    /**
     * 查询tb_collections中的所有的sku
     * @param page
     * @param rows
     * @param enable
     * @return
     */
    public PageResult<Collect> findAllSkusBySkuId(Integer page, Integer rows, Boolean enable) {
        PageHelper.startPage(page,rows);
        Example example = new Example(Collect.class);
        Example.Criteria criteria = example.createCriteria();
        if(enable!=null){
            criteria.andEqualTo(enable);
        }
        Page<Collect> pageInfo = (Page<Collect>) collectMapper.selectByExample(example);
        PageResult<Collect> skuPageInfo = new PageResult<>();

        List<Collect> collects = pageInfo.getResult();
        for (Collect collect : collects) {
            Long skuId = collect.getSkuId();
            Sku sku = goodsClient.querySkuById(skuId);
            collect.setCurrentPrice(sku.getPrice());
            collect.setNum(1);
        }
        skuPageInfo.setItems(collects);
        skuPageInfo.setTotalPage(pageInfo.getPages());
        skuPageInfo.setTotal(pageInfo.getTotal());
        return skuPageInfo;
    }

    @Transactional(rollbackFor=Exception.class)
    public Boolean deleteCollectionById(Collect collect) {
        try {
            Cart cart = new Cart();
            cart.setUserId(collect.getUserId());
            cart.setTitle(collect.getTitle());
            cart.setNum(collect.getNum());
            cart.setImage(collect.getImage());
            cart.setOwnSpec(collect.getOwnSpec());
            cart.setPrice(collect.getPrice());
            cart.setSkuId(collect.getSkuId());
            cart.setNum(1);

            addCart(cart);

            collectMapper.deleteByPrimaryKey(collect.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public void addCart(Cart cart) {
        //获得用户信息
        UserInfo user = LoginInterceptor.getLoginUser();
        System.out.println(user);
        //获得该用户购物车的Key值
        String key = KEY_PREFIX2+ user.getId();
        //从redis中获得购物车的操作对象
        BoundHashOperations<String, Object, Object> hashOps = redisTemplate.boundHashOps(key);

        //获得Cart中传递过来的数据
        Long skuId = cart.getSkuId();
        Integer num = cart.getNum();
        //判断该商品是否存在
        if (hashOps.hasKey(skuId.toString())) {
            //存在,数量相加
            String json = hashOps.get(skuId.toString()).toString();
            cart = JsonUtils.parse(json, Cart.class);
            cart.setNum(cart.getNum() + num);
        }
        
        //将数据写入redis中
        hashOps.put(skuId.toString(), JsonUtils.serialize(cart));
    }
}
